#ifndef _DISK_PARTION_H
#define  _DISK_PARTION_H

#include "scsi_dev.h"

#include <vector>
using namespace std;

typedef struct _mbrpart {
	unsigned char active;
	unsigned char shead; // CHS start value, not used by program
	unsigned char ssect; // CHS start value, not used by program
	unsigned char scyl; // CHS start value, not used by program
	unsigned char type;
	unsigned char ehead; // CHS end value, not used by program
	unsigned char esect; // CHS end value, not used by program
	unsigned char ecyl; // CHS end value, not used by program
	uint32_t start;
	uint32_t len;
}mbrpart_s;

#pragma pack(push)
#pragma pack(1)
#define MBR_N_PRI_PARTITIONS	4
typedef struct _DosRawTable {
	char			boot_code [440];
	uint32_t        mbr_signature;	/* really a unique ID */
	uint16_t        Unknown;
	mbrpart_s		partitions [MBR_N_PRI_PARTITIONS];
	uint16_t		magic;
}mbrtable_s;
#pragma pack(pop)

typedef struct __guid
{
	uint32_t data1;
	uint16_t data2;
	uint16_t data3;
	uint64_t data4;
}guid_s;

typedef struct _gptpart{
	guid_s type;
	guid_s uuID;
	uint64_t start;
	uint64_t end;
	uint64_t flags;
	char name[72];
}gptpart_s;


typedef struct _gpthdr
{
	unsigned char magic[8];
	unsigned char version[4];
	uint32_t hdrlen;
	uint32_t hdrsum;
	uint32_t pad;
	uint64_t this_hdr;
	uint64_t other_hdr;
	uint64_t data_start;
	uint64_t data_end;
	guid_s guid;
	uint64_t first_entry;
	uint32_t entry_cnt;
	uint32_t entry_len;
	uint32_t part_sum;
}gpthdr_s;



struct mbrpart {
	unsigned char active;
	unsigned char shead; // CHS start value, not used by program
	unsigned char ssect; // CHS start value, not used by program
	unsigned char scyl;  // CHS start value, not used by program
	unsigned char type;
	unsigned char ehead; // CHS end value, not used by program
	unsigned char esect; // CHS end value, not used by program
	unsigned char ecyl;  // CHS end value, not used by program
	uint32_t start;
	uint32_t len;
};

typedef struct _STFS_TABLE_
{
	char     magic[8];
	uint32_t version;
	uint32_t status;  //状态   0x6666 正常 0x1111 正在格式化  
	
	//¼���ļ���Ϣ
	uint64_t baseRecLBA;
	uint32_t recFileSize;
	uint32_t recNum;

	uint64_t basePicLBA;
	uint32_t picFileSize;
	uint32_t picFileNum;

	//¼�������ļ�
	uint64_t recIndexLBA;
	uint32_t recIndexSize;
	uint32_t recIndexNum;

	//ͼƬ�����ļ�
	uint64_t picIndexLBA;
	uint32_t picIndexFileSize;
	uint32_t picIndexFileNum;

	//ϵͳ��־�ļ�
	uint64_t sysLogLBA;
	uint32_t sysLogFileSize;
	uint32_t sysLogNum;
//#ifdef _SPT_DBG_LOG_
	//ϵͳ������־
	uint64_t dbgLogLBA;
	uint32_t dbgLogFileSize;
	uint32_t dbgLogNum;

	uint32_t create_tm; // 创建时间

//#endif
}STFS_TABLE_S,*PSTFS_TABLE_S;


enum FSTYPE
{
	FSTYPE_NONE      =  0x00,
	FSTYPE_FAT32     =  0x0B,
	FSTYPE_NTFS      =  0x07,
	FSTYPE_RESERVED  =  0x27,	//΢����������
};

typedef vector<gptpart_s> VEC_DISKPART;
typedef vector<mbrpart_s> VEC_MBRPART;

class CDiskTable
{
public:
    CDiskTable(CDisk_Dev* pDev);
     CDiskTable();
	~CDiskTable(void);
protected:
	CDisk_Dev* m_pdev;
	unsigned char * m_part_buf;	//������Ϣ�Ļ��壬 ����GPT��MBR
	VEC_DISKPART m_vec_gptpart;	//GPT����������
	VEC_MBRPART  m_vec_mbrpart;	//MBR����
	uint64_t     m_recFileLBA;	//¼���ļ��׵�ַ
	uint32_t     m_recFileSecs; //�ļ�ռ�ö��ٸ�����
	uint64_t     m_recIndexLBA;	//¼��������ַ
	uint64_t	 m_sysLogLBA;	//��־�ļ�Ӳ�̵�ַ
	uint64_t	 m_picIndexLBA;	//ͼƬ�ļ����׵�ַ
	uint64_t	 m_dbgLogLBA;	//������־���׵�ַ
	uint32_t     m_dbgLogSize;	//��־
	uint64_t     m_bak_lba;		//
	uint32_t     m_recFileNum;
	uint32_t     m_comPartMB;  //ͨ���̴�С
	uint32_t     m_stfs_status;
	uint32_t     m_create_tm;  //创建时间
	bool         m_isGPT;				//�Ƿ�ΪGPT����
	bool		 m_bInitSTFS;			//�Ƿ��Ѿ��̻�
	bool         m_bUseMBR;   //����С��2T��Ӳ��ʹ��MBR����
protected:
	int AssignMBR(unsigned char* data_buf);				//����MBR����
	int AssignGPT(unsigned char* data_buf);				//����GPT����
public:

	int Init(CDisk_Dev* pDev);
	int ReadSTFSTable();
	int DetectPartitionTable();
	int AnalyseRecordPart();
	uint64_t GetTotalSec();
	int GetPartNum();		//��ȡ�����ĸ���
	uint64_t GetPartitionSec(int part_no);		//��ȡ��������								//��ȡĳ��������
	uint64_t GetPartitionStart(int part_no);    //��ȡ�����Ŀ�ʼ��ַ
	int GetBootInfo(int part_no,unsigned char* boot_buf,uint64_t* start_lba);//��ȡĳ������������������Ϣ����ʼ����LBA

	int CheckFSTypeOfPart(FSTYPE & fsType, unsigned char * buf ,int bufSize);
	int CheckFSTypeNonePart(CDisk_Dev * pDev);
	int GetFsType(uchar_t * dataBuf,int bufSize);
	uint32_t GetCreateTime()
	{
		return m_create_tm;
	}
	int GetStatus()
	{
		return m_stfs_status;
	}
public:
	bool isGPT()
	{
		return m_isGPT;
	}

	VEC_DISKPART * GetGPTPart()
	{
		return &m_vec_gptpart;
	}

	uint64_t GetRecIndexLBA()
	{
		return m_recIndexLBA;
	}

	uint64_t GetSysLogLBA()
	{
		return m_sysLogLBA;
	}
	
	uint64_t GetPicLBA()
	{
		return m_picIndexLBA;
	}

	uint64_t GetDbgLogLBA()
	{
		return m_dbgLogLBA;
	}
	uint32_t GetDbgLogSize()
	{
		return m_dbgLogSize;
	}
	bool IsInitSTFS()
	{
		return m_bInitSTFS;
	}

	uint32_t GetRecFileNum()
	{
		return	 m_recFileNum;
	}
	uint64_t GetRecFileLBA()
	{
		return m_recFileLBA;
	}
	uint32_t GetRecFileSecs()
	{
		return m_recFileSecs;
	}
	void SetUseMBR(bool bUseMBR)
	{
		m_bUseMBR = bUseMBR;
	}
public:	//��չ��֧�ַ�������
	int SetDataPart( uint32_t fileSizeMB,uint32_t indexInfoSize,uint32_t picPartSizeMB,uint32_t sysBaseSizeMB,uint32_t debugLogMB = 0); //����Ӳ�̵Ĵ�С�ȷֳɼ�������
	
	int SetComPart( uint32_t fileSizeMB,uint32_t indexInfoSize, uint32_t usespaceGB);

	int SetMBRPart( uint32_t fileSizeMB,uint32_t indexInfoSize, uint32_t usePartGB = 0);
	int SetMBROnePart( uint32_t fileSizeMB,uint32_t indexInfoSize);
	int SetParttion_Format(uint32_t fileSizeMB,uint32_t indexInfoSize, uint32_t comPartMB, uint32_t usespaceGB);
	int SetOneParttion_Format(uint32_t fileSizeMB,uint32_t indexInfoSize);
    int FomatUSBDiskAssignFile(uint32_t fileSizeMB,uint32_t indexInfoSize,uint32_t reserveSpace = 0,uint32_t limit_AssignMB = 0);
	int FormatFAT32_AssignFile(uint64_t startSecs,uint64_t partSecs,uint32_t fileSize,uint32_t reseveMB = 0,uint32_t limit_AssignMB = 0);

	int FormatFat32(int partNO,uint64_t totalSec = 0);
	//С��2TBӲ�̵�ʹ�÷�����ʽ
	int SetCommonMBRPartition(int partNum = 1);
	//����2TB���̷���
	int SetCommonGPTPartition(int partNum = 1);

	int InitSTFSTable(uint32_t fileSizeMB, uint32_t indexInfoSize, int recNum, int status = 0x1111);
protected:
	void SetGptHead(struct _gptpart* pGptTable,struct _gpthdr * pGptHdr);

	void SetBakGptHead(struct _gpthdr * pGptHdr);

	int GptPartInit(struct _gptpart * pGptpart,unsigned char partType);

	void swap_uuid_and_efi_guid (unsigned char* uuID);

};

#define DEF_MBR_SECTOR	   0
#define DEF_SECTOR_SIZE    512		//Ĭ�ϴ��̷�������������ռ���ֽ�����
#define SECTOR_4K		   4096    //������4K����

#define GPT_HDR_START      1	//��GPT����ʼ��ַ	��512�ֽ�Ϊ��λ
#define GPT_TABLE_START	   2    //�ڶ���������GPT���׵�ַ ������СĬ��Ϊ512�ֽ�
#define GPT_PARTTION	   34   //��һ��GPT��������ʼ������ַ
#define GTP_BAK_SEC		   33   //����GPTռ����33��������32����λ�����洢GPT����������1�������洢GPTͷ
#define MAX_GPT_PART_NUM   128  //���֧�ֵ�GPT������Ŀ
#define GPT_TABLE_LEN      32   //��������ռ
#define GPT_PERPART_SIZE   128  //ÿ������������ռ���ֽ���

#define GPT_MAGIC		 {0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54} // "EFI PART"
#define STFS_TABLE_MAGIC {0x53, 0x54, 0x46, 0x53, 0x50, 0x41, 0x52, 0x54} // "STFSPART"
#define STFS_TABLE_VERSION	mmioFOURCC('0','0','1','0');
#define STFS_TABLE_INIT_OK   0x6666
#define STFS_TABLE_FORMATTING 0x1111

#define GPT_V1 {0x00, 0x00, 0x01, 0x00}
#define MBR_MAGIC				0xAA55
#define PARTITION_MAGIC_MAGIC	0xf6f6
#define STR_FAT					"FAT"
#define STFS_ALL_PART			-1
#define SYS_PART_RESERVE_SECS 64
#define DEF_STFS_RESERVER_SECS 2048
#define STFS_TABLE_LBA		 64
#define STFS_TABLE_BAK_LBA   88  //-34
#define DEF_PART_START       2048
#define DEF_GPTBACKUP_PART_NAME "STFS backup partition" 
#define BOOT_SECTOR_MAGIC     0xAA55      
#endif //_DISK_PARTION_H
